use status::*;
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};
use x11::xlib::{XCloseDisplay, XDefaultRootWindow, XFlush, XOpenDisplay, XStoreName};

fn main() -> std::io::Result<()> {
    let term = Arc::new(AtomicBool::new(false));
    term.store(false, Ordering::Relaxed);
    signal_hook::flag::register(signal_hook::consts::SIGINT, Arc::clone(&term))?;

    let config: Vec<(
        &'static str,
        u16,
        fn(Option<&str>) -> Option<String>,
        Option<&'static str>,
    )> = vec![
        (
            "",
            300,
            cmd,
            Some("feh --recursive --randomize --bg-fill ~/Pictures/wallpapers"),
        ),
        (" ", 1, get_velocity_str, None),
        (" 💿 ", 2, get_mem_available, None),
        (" ", 1, get_vol, None),
        (" ", 30, get_bat_status, None),
        (" ", 30, get_bat_capacity, None),
        ("% 📆 ", 8, get_time, None),
    ];

    let mut init = vec![];
    config.iter().for_each(|x| {
        init.push(x.2(x.3));
    });

    let dpy = unsafe { XOpenDisplay(std::ptr::null()) };
    let mut num: u16 = 0;
    loop {
        num = num.overflowing_add(1).0;
        config.iter().enumerate().for_each(|(i, x)| {
            if num % x.1 == 0 {
                if let Some(elem) = init.get_mut(i) {
                    *elem = x.2(x.3);
                }
            }
        });
        let mut result = String::new();
        init.iter().enumerate().for_each(|(i, x)| {
            if let Some(block) = x {
                result.push_str(config[i].0);
                result.push_str(block);
            }
        });
        result.push('\0');
        unsafe {
            XStoreName(dpy, XDefaultRootWindow(dpy), result.as_ptr() as *const i8);
            // XSync(dpy, 0);
            XFlush(dpy);
        }
        std::thread::sleep(std::time::Duration::from_secs(INTERVAL));
        if term.load(Ordering::Relaxed) {
            break;
        };
    }
    unsafe { XCloseDisplay(dpy) };
    Ok(())
}
